package main

import "fmt"

/**
<pre>
	1、定义结构体：
	type 结构体名称 struct {

	}
	2、使用 new() 方法返回的是地址，里面的值默认都是zero value
	3、go语言中没有构造方法
	4、给结构体定义方法，普通方法和引用传递方法的传递的区别
	5、只有指针才可以改变结构体内容
	6、nil 也可以调用方法
	7、一个目录下只能有一个包
	8、首字母大写代表public,小写代表private
	9、为结构定义的方法必须放在同一个包内，可以是不同文件
</pre>
*/

type TreeNode struct {
	value int
	// 左右子树是一个指针类型
	left, right *TreeNode
}

/**
给结构体定义方法：
func (结构体类型) 方法名([方法参数])[返回值]{

}
*/
func (node TreeNode) print(params int) string {
	fmt.Println("println tree value:", node.value)
	return "ok"
}

/**
此时该方法是值传递，不会改变TreeNode中的值
*/
func (node TreeNode) setValue(value int) {
	node.value = value
}

/**
此时该方法是引用传递，会改变TreeNode中的值
*/
func (node *TreeNode) setValue2(value int) {
	if nil == node {
		fmt.Println("set value to nil node,ignore")
		return
	}
	node.value = value
}

/**
定一个一个方法，创建TreeNode对象,此时返回了局部变量的地址
*/
func createTreeNode(value int) *TreeNode {
	return &TreeNode{value: value}
}

func main() {
	var root TreeNode
	root = TreeNode{value: 10}
	root.left = &TreeNode{}
	root.right = &TreeNode{20, nil, nil}
	// 使用 new() 方法返回的是地址，里面的值默认都是zero value
	root.right.left = new(TreeNode)
	root.right.right = createTreeNode(60)

	// 调用给结构体的方法
	root.print(root.value + 1)

	// 此时调用的是值传递的方法，不会改变root中的value
	root.setValue(80)
	root.print(root.value + 1)

	// 此时调用的是引用传递的方法，会改变root中的value
	root.setValue2(90)
	root.print(root.value + 1)

	// slice 中可以这样初始化对象
	nodes := []TreeNode{
		{value: 30},
		{},
		{50, nil, &root},
	}

	for node := range nodes {
		fmt.Println(node)
	}
}
